home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / swtools / mipsABI / examples / sup / PORT / step03 / supcmain.c < prev    next >
Encoding:
Text File  |  1994-08-02  |  21.9 KB  |  729 lines

  1. /*
  2.  * Copyright (c) 1992 Carnegie Mellon University
  3.  * All Rights Reserved.
  4.  * 
  5.  * Permission to use, copy, modify and distribute this software and its
  6.  * documentation is hereby granted, provided that both the copyright
  7.  * notice and this permission notice appear in all copies of the
  8.  * software, derivative works or modified versions, and any portions
  9.  * thereof, and that both notices appear in supporting documentation.
  10.  *
  11.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  12.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  13.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  14.  *
  15.  * Carnegie Mellon requests users of this software to return to
  16.  *
  17.  *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
  18.  *  School of Computer Science
  19.  *  Carnegie Mellon University
  20.  *  Pittsburgh PA 15213-3890
  21.  *
  22.  * any improvements or extensions that they make and grant Carnegie Mellon
  23.  * the rights to redistribute these changes.
  24.  */
  25. /*
  26.  *    sup -- Software Upgrade Protocol client process
  27.  *
  28.  *    Usage:  sup [ flags ] [ supfile ] [ collection ... ]
  29.  *
  30.  *    The only required argument to sup is the name of a supfile.  It
  31.  *    must either be given explicitly on the command line, or the -s
  32.  *    flag must be specified.  If the -s flag is given, the system
  33.  *    supfile will be used and a supfile command argument should not be
  34.  *    specified.  The list of collections is optional and if specified
  35.  *    will be the only collections upgraded.  The following flags affect
  36.  *    all collections specified.
  37.  *
  38.  *    -s    "system upgrade" flag
  39.  *            As described above.
  40.  *
  41.  *    -t    "upgrade time" flag
  42.  *            When this flag is given, Sup will print the time
  43.  *            that each collection was last upgraded, rather than
  44.  *            performing actual upgrades.
  45.  *
  46.  *    -R    "resource pause" flag
  47.  *            Sup will not disable resource pausing and will not
  48.  *            make filesystem space checks.
  49.  *
  50.  *    -N    "debug network" flag
  51.  *            Sup will trace messages sent and received that
  52.  *            implement the Sup network protocol.
  53.  *
  54.  *    -P    "debug ports" flag
  55.  *                Sup will use a set of non-privileged network
  56.  *            ports reserved for debugging purposes.
  57.  *
  58.  *    -X    "crosspatch" flag
  59.  *                Sup is being run remotely with a crosspatch.
  60.  *            Need to be carefull as we may be running as root
  61.  *            instead of collection owner.
  62.  *
  63.  *    The remaining flags affect all collections unless an explicit list
  64.  *    of collections are given with the flags.  Multiple flags may be
  65.  *    specified together that affect the same collections.  For the sake
  66.  *    of convience, any flags that always affect all collections can be
  67.  *    specified with flags that affect only some collections.  For
  68.  *    example, "sup -sde=coll1,coll2" would perform a system upgrade,
  69.  *    and the first two collections would allow both file deletions and
  70.  *    command executions.  Note that this is not the same command as
  71.  *    "sup -sde=coll1 coll2", which would perform a system upgrade of
  72.  *    just the coll2 collection and would ignore the flags given for the
  73.  *    coll1 collection.
  74.  *
  75.  *    -a    "all files" flag
  76.  *            All files in the collection will be copied from
  77.  *            the repository, regardless of their status on the
  78.  *            current machine.  Because of this, it is a very
  79.  *            expensive operation and should only be done for
  80.  *            small collections if data corruption is suspected
  81.  *            and been confirmed.  In most cases, the -o flag
  82.  *            should be sufficient.
  83.  *
  84.  *    -b    "backup files" flag
  85.  *            If the -b flag if given, or the "backup" supfile
  86.  *            option is specified, the contents of regular files
  87.  *            on the local system will be saved before they are
  88.  *            overwritten with new data.  The data will be saved
  89.  *            in a subdirectory called "BACKUP" in the directory
  90.  *            containing the original version of the file, in a
  91.  *            file with the same non-directory part of the file
  92.  *            name.  The files to backup are specified by the
  93.  *            list file on the repository.
  94.  *
  95.  *    -B    "don't backup files" flag
  96.  *            The -B flag overrides and disables the -b flag and
  97.  *            the "backup" supfile option.
  98.  *
  99.  *    -d    "delete files" flag
  100.  *            Files that are no longer in the collection on the
  101.  *            repository will be deleted if present on the local
  102.  *            machine.  This may also be specified in a supfile
  103.  *            with the "delete" option.
  104.  *
  105.  *    -D    "don't delete files" flag
  106.  *            The -D flag overrides and disables the -d flag and
  107.  *            the "delete" supfile option.
  108.  *
  109.  *    -e    "execute files" flag
  110.  *            Sup will execute commands sent from the repository
  111.  *            that should be run when a file is upgraded.  If
  112.  *            the -e flag is omitted, Sup will print a message
  113.  *            that specifies the command to execute.  This may
  114.  *            also be specified in a supfile with the "execute"
  115.  *            option.
  116.  *
  117.  *    -E    "don't execute files" flag
  118.  *            The -E flag overrides and disables the -e flag and
  119.  *            the "execute" supfile option.
  120.  *
  121.  *    -f    "file listing" flag
  122.  *            A "list-only" upgrade will be performed.  Messages
  123.  *            will be printed that indicate what would happen if
  124.  *            an actual upgrade were done.
  125.  *
  126.  *    -k    "keep newer files" flag
  127.  *            The -k flag, or "keep" supfile option, will cause
  128.  *            Sup to check to see whether there is a newer file on
  129.  *            the local disk before updating files.  Only files
  130.  *            which are newer on the repository will be updated.
  131.  *
  132.  *    -K    "don't keep newer files" flag
  133.  *            The -K flag overrides and disables the -k flag and
  134.  *            the "keep" supfile option.
  135.  *
  136.  *    -l    "local upgrade" flag
  137.  *            Normally, Sup will not upgrade a collection if the
  138.  *            repository is on the same machine.  This allows
  139.  *            users to run upgrades on all machines without
  140.  *            having to make special checks for the repository
  141.  *            machine.  If the -l flag is specified, collections
  142.  *            will be upgraded even if the repository is local.
  143.  *
  144.  *    -m    "mail" flag
  145.  *            Normally, Sup used standard output for messages.
  146.  *            If the -m flag if given, Sup will send mail to the
  147.  *            user running Sup, or a user specified with the
  148.  *            "notify" supfile option, that contains messages
  149.  *            printed by Sup.
  150.  *
  151.  *    -o    "old files" flag
  152.  *            Sup will normally only upgrade files that have
  153.  *            changed on the repository since the last time an
  154.  *            upgrade was performed.  The -o flag, or the "old"
  155.  *            supfile option, will cause Sup to check all files
  156.  *            in the collection for changes instead of just the
  157.  *            new ones.
  158.  *
  159.  *    -O    "not old files" flag
  160.  *            The -O flag overrides and disables the -o flag and
  161.  *            the "old" supfile option.
  162.  *
  163.  *    -v    "verbose" flag
  164.  *            Normally, Sup will only print messages if there
  165.  *            are problems.  This flag causes Sup to also print
  166.  *            messages during normal progress showing what Sup
  167.  *            is doing.
  168.  *
  169.  **********************************************************************
  170.  * HISTORY
  171.  *
  172.  * 7-July-93  Nate Williams at Montana State University
  173.  *    Modified SUP to use gzip based compression when sending files
  174.  *    across the network to save BandWidth
  175.  *
  176.  * $Log: supcmain.c,v $
  177.  * Revision 1.3  1993/08/04  17:46:17  brezak
  178.  * Changes from nate for gzip'ed sup
  179.  *
  180.  * Revision 1.2  1993/05/24  17:57:28  brezak
  181.  * Remove netcrypt.c. Remove unneeded files. Cleanup make.
  182.  *
  183.  * Revision 1.1.1.1  1993/05/21  14:52:18  cgd
  184.  * initial import of CMU's SUP to NetBSD
  185.  *
  186.  * Revision 1.6  92/08/11  12:06:59  mrt
  187.  *     Merged in Brad's changes. Made resource pausing code conditional
  188.  *     on MACH, rather than CMUCS. Fixed some calls to sprintf to
  189.  *     return void.
  190.  *     [92/08/09            mrt]
  191.  * 
  192.  * Revision 1.5  92/02/08  19:01:18  mja
  193.  *     Correct oldsigsys type when ANSI C.
  194.  *     [92/02/08  18:59:47  mja]
  195.  * 
  196.  * Revision 1.4  92/02/08  18:24:01  mja
  197.  *     Added -k and -K switches.
  198.  *     [92/01/17            vdelvecc]
  199.  * 
  200.  * 27-Dec-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  201.  *    Added crosspatch support (is currently ignored).
  202.  *
  203.  * 28-Jun-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  204.  *    Added code for "release" support.
  205.  *
  206.  * 25-May-87  Doug Philips (dwp) at Carnegie-Mellon University
  207.  *    Split into several files.  This is the main program and
  208.  *    command line processing and old history log. [V5.21]
  209.  *
  210.  * 21-May-87  Chriss Stephens (chriss) at Carnegie Mellon University
  211.  *    Merged divergent CS and ECE versions. ifdeffed out the resource
  212.  *    pausing code - only compiled in if CMUCS defined. [V5.21a]
  213.  *
  214.  * 20-May-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  215.  *    Removed support for version 3 of SUP protocol.  Added changes
  216.  *    to make lint happy.  Added calls to new logging routines. [V5.20]
  217.  *
  218.  * 01-Apr-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
  219.  *    Added -R switch to reenable resource pausing, which is currently
  220.  *    disabled by default.  Added code to check for free disk space
  221.  *    available on the target filesystem so that sup shouldn't run the
  222.  *    system out of disk space as frequently. [V5.19]
  223.  *
  224.  * 19-Sep-86  Mike Accetta (mja) at Carnegie-Mellon University
  225.  *    Changed default supfile name for system collections when -t
  226.  *    is specified to use FILESUPTDEFAULT; added missing new-line
  227.  *    in retry message. [V5.18]
  228.  *
  229.  * 21-Jun-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  230.  *    Missed a caller to a routine which had an extra argument added
  231.  *    to it last edit. [V5.17]
  232.  *
  233.  * 07-Jun-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  234.  *    Changed getcoll() so that fatal errors are checked immediately
  235.  *    instead of after sleeping for a little while.  Changed all
  236.  *    rm -rf commands to rmdir since the Mach folks keep deleting
  237.  *    their root and /usr directory trees.  Reversed the order of
  238.  *    delete commands to that directories will possibly empty so
  239.  *    that the rmdir's work. [V5.16]
  240.  *
  241.  * 30-May-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  242.  *    Changed temporary file names to #n.sup format. [V5.15]
  243.  *
  244.  * 19-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  245.  *    Moved PGMVERSION to supvers.c module. [V5.14]
  246.  *
  247.  * 06-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  248.  *    Added check for file type before unlink when receiving a
  249.  *    symbolic link.  Now runs "rm -rf" if the file type is a
  250.  *    directory. [V5.13]
  251.  *
  252.  * 03-Feb-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  253.  *    Fixed small bug in signon that didn't retry connections if an
  254.  *    error occured on the first attempt to connect. [V5.12]
  255.  *
  256.  * 26-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  257.  *    New command interface.  Added -bBDEO flags and "delete",
  258.  *    "execute" and "old" supfile options.  Changed -d to work
  259.  *    correctly without implying -o. [V5.11]
  260.  *
  261.  * 21-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  262.  *    Fix incorrect check for supfile changing.  Flush output buffers
  263.  *    before restart. [V5.10]
  264.  *
  265.  * 17-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  266.  *    Add call to requestend() after connection errors are retried to
  267.  *    free file descriptors. [V5.9]
  268.  *
  269.  * 15-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  270.  *    Fix SERIOUS merge error from previous edit.  Added notify
  271.  *    when execute command fails. [V5.8]
  272.  *
  273.  * 11-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  274.  *    Changed ugconvert to clear setuid/setgid bits if it doesn't use
  275.  *    the user and group specified by the remote system.  Changed
  276.  *    execute code to invalidate collection if execute command returns
  277.  *    with a non-zero exit status.  Added support for execv() of
  278.  *    original arguments of supfile is upgraded sucessfully.  Changed
  279.  *    copyfile to always use a temp file if possible. [V5.7]
  280.  *
  281.  * 04-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
  282.  *    Added support for fileserver busy messages and new nameserver
  283.  *    protocol to support multiple repositories per collection.
  284.  *    Added code to lock collections with lock files. [V5.6]
  285.  *
  286.  * 29-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  287.  *    Major rewrite for protocol version 4. [V4.5]
  288.  *
  289.  * 12-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  290.  *    Changed to check for DIFFERENT mtime (again). [V3.4]
  291.  *
  292.  * 08-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  293.  *    Replaced [ug]convert routines with ugconvert routine so that an
  294.  *    appropriate group will be used if the default user is used.
  295.  *    Changed switch parsing to allow multiple switches to be specified
  296.  *    at the same time. [V3.3]
  297.  *
  298.  * 04-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  299.  *    Added test to request a new copy of an old file that already
  300.  *    exists if the mtime is different. [V3.2]
  301.  *
  302.  * 24-Nov-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  303.  *    Added -l switch to enable upgrades from local repositories.
  304.  *
  305.  * 03-Nov-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  306.  *    Minor change in order -t prints so that columns line up.
  307.  *
  308.  * 22-Oct-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  309.  *    Added code to implement retry flag and pass this on to request().
  310.  *
  311.  * 22-Sep-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
  312.  *    Merged 4.1 and 4.2 versions together.
  313.  *
  314.  * 04-Jun-85  Steven Shafer (sas) at Carnegie-Mellon University
  315.  *    Created for 4.2 BSD.
  316.  *
  317.  **********************************************************************
  318.  */
  319.  
  320. #define MSGFILE
  321. #include "supcdefs.h"
  322. #if    MACH
  323. #include <sys/syscall.h>
  324. #ifndef SYS_rpause
  325. #define SYS_rpause    (-5)
  326. #endif
  327. #endif
  328.  
  329. /*********************************************
  330.  ***    G L O B A L   V A R I A B L E S    ***
  331.  *********************************************/
  332.  
  333. char program[] = "SUP";            /* program name for SCM messages */
  334. int progpid = -1;            /* and process id */
  335.  
  336. COLLECTION *firstC,*thisC;        /* collection list pointer */
  337.  
  338. extern int dontjump;            /* disable longjmp */
  339. extern int scmdebug;            /* SCM debugging flag */
  340.  
  341. int sysflag;                /* system upgrade flag */
  342. int timeflag;                /* print times flag */
  343. #if    MACH
  344. int rpauseflag;                /* don't disable resource pausing */
  345. #endif    /* MACH */
  346. int xpatchflag;                /* crosspatched with remote system */
  347. int portdebug;                /* network debugging ports */
  348.  
  349. /*************************************
  350.  ***    M A I N   R O U T I N E    ***
  351.  *************************************/
  352.  
  353. main (argc,argv)
  354. int argc;
  355. char **argv;
  356. {
  357.     char *init ();
  358.     char *progname,*supfname;
  359.     int restart,sfdev,sfino,sfmtime;
  360.     struct stat sbuf;
  361. #ifdef _ABI_SOURCE
  362.     struct sigaction ignvec,oldvec;
  363. #else
  364.     struct sigvec ignvec,oldvec;
  365. #endif
  366.  
  367.     /* initialize global variables */
  368.     pgmversion = PGMVERSION;    /* export version number */
  369.     server = FALSE;            /* export that we're not a server */
  370.     collname = NULL;        /* no current collection yet */
  371.     dontjump = TRUE;        /* clear setjmp buffer */
  372.     progname = salloc (argv[0]);
  373.  
  374.     supfname = init (argc,argv);
  375.     restart = -1;            /* don't make restart checks */
  376.     if (*progname == '/' && *supfname == '/') {
  377.         if (stat (supfname,&sbuf) < 0)
  378.             logerr ("Can't stat supfile %s",supfname);
  379.         else {
  380.             sfdev = sbuf.st_dev;
  381.             sfino = sbuf.st_ino;
  382.             sfmtime = sbuf.st_mtime;
  383.             restart = 0;
  384.         }
  385.     }
  386.     if (timeflag) {
  387.         for (thisC = firstC; thisC; thisC = thisC->Cnext)
  388.             prtime ();
  389.     } else {
  390.         /* ignore network pipe signals */
  391. #ifdef _ABI_SOURCE
  392.         ignvec.sa_handler = SIG_IGN;
  393.         ignvec.sa_flags = 0;
  394.         sigemptyset (&(ignvec.sa_mask));
  395.         (void) sigaction (SIGPIPE,&ignvec,&oldvec);
  396. #else
  397.         ignvec.sv_handler = SIG_IGN;
  398.         ignvec.sv_onstack = 0;
  399.         ignvec.sv_mask = 0;
  400.         (void) sigvec (SIGPIPE,&ignvec,&oldvec);
  401. #endif
  402.         getnams ();        /* find unknown repositories */
  403.         for (thisC = firstC; thisC; thisC = thisC->Cnext) {
  404.             getcoll ();    /* upgrade each collection */
  405.             if (restart == 0) {
  406.                 if (stat (supfname,&sbuf) < 0)
  407.                     logerr ("Can't stat supfile %s",
  408.                         supfname);
  409.                 else if (sfmtime != sbuf.st_mtime ||
  410.                      sfino != sbuf.st_ino ||
  411.                      sfdev != sbuf.st_dev) {
  412.                     restart = 1;
  413.                     break;
  414.                 }
  415.             }
  416.         }
  417.         endpwent ();        /* close /etc/passwd */
  418.         (void) endgrent ();    /* close /etc/group */
  419.         if (restart == 1) {
  420.             int fd;
  421.             loginfo ("SUP Restarting %s with new supfile %s",
  422.                 progname,supfname);
  423.             for (fd = getdtablesize (); fd > 3; fd--)
  424.                 (void) close (fd);
  425.             execv (progname,argv);
  426.             logquit (1,"Restart failed");
  427.         }
  428.     }
  429.     while (thisC = firstC) {
  430.         firstC = firstC->Cnext;
  431.         free (thisC->Cname);
  432.         Tfree (&thisC->Chtree);
  433.         free (thisC->Cbase);
  434.         if (thisC->Chbase)  free (thisC->Chbase);
  435.         if (thisC->Cprefix)  free (thisC->Cprefix);
  436.         if (thisC->Crelease)  free (thisC->Crelease);
  437.         if (thisC->Cnotify)  free (thisC->Cnotify);
  438.         if (thisC->Clogin)  free (thisC->Clogin);
  439.         if (thisC->Cpswd)  free (thisC->Cpswd);
  440.         if (thisC->Ccrypt)  free (thisC->Ccrypt);
  441.         free ((char *)thisC);
  442.     }
  443.     exit (0);
  444. }
  445.  
  446. /*****************************************
  447.  ***    I N I T I A L I Z A T I O N    ***
  448.  *****************************************/
  449. /* Set up collection list from supfile.  Check all fields except
  450.  * hostname to be sure they make sense.
  451.  */
  452.  
  453. #define Toflags    Tflags
  454. #define Taflags    Tmode
  455. #define Twant    Tuid
  456. #define Tcount    Tgid
  457.  
  458. doswitch (argp,collTp,oflagsp,aflagsp)
  459. char *argp;
  460. register TREE **collTp;
  461. int *oflagsp,*aflagsp;
  462. {
  463.     register TREE *t;
  464.     register char *coll;
  465.     register int oflags,aflags;
  466.  
  467.     oflags = aflags = 0;
  468.     for (;;) {
  469.         switch (*argp) {
  470.         default:
  471.             logerr ("Invalid flag '%c' ignored",*argp);
  472.             break;
  473.         case '\0':
  474.         case '=':
  475.             if (*argp++ == '\0' || *argp == '\0') {
  476.                 *oflagsp |= oflags;
  477.                 *oflagsp &= ~aflags;
  478.                 *aflagsp |= aflags;
  479.                 *aflagsp &= ~oflags;
  480.                 return;
  481.             }
  482.             do {
  483.                 coll = nxtarg (&argp,", \t");
  484.                 t = Tinsert (collTp,coll,TRUE);
  485.                 t->Toflags |= oflags;
  486.                 t->Toflags &= ~aflags;
  487.                 t->Taflags |= aflags;
  488.                 t->Taflags &= ~oflags;
  489.                 argp = skipover (argp,", \t");
  490.             } while (*argp);
  491.             return;
  492.         case 'N':
  493.             scmdebug++;
  494.             break;
  495.         case 'P':
  496.             portdebug = TRUE;
  497.             break;
  498.         case 'R':
  499. #if    MACH
  500.             rpauseflag = TRUE;
  501. #endif    /* MACH */
  502.             break;
  503.         case 'X':
  504.             xpatchflag = TRUE;
  505.             break;
  506.         case 's':
  507.             sysflag = TRUE;
  508.             break;
  509.         case 't':
  510.             timeflag = TRUE;
  511.             break;
  512.         case 'a':
  513.             oflags |= CFALL;
  514.             break;
  515.         case 'b':
  516.             oflags |= CFBACKUP;
  517.             aflags &= ~CFBACKUP;
  518.             break;
  519.         case 'B':
  520.             oflags &= ~CFBACKUP;
  521.             aflags |= CFBACKUP;
  522.             break;
  523.         case 'd':
  524.             oflags |= CFDELETE;
  525.             aflags &= ~CFDELETE;
  526.             break;
  527.         case 'D':
  528.             oflags &= ~CFDELETE;
  529.             aflags |= CFDELETE;
  530.             break;
  531.         case 'e':
  532.             oflags |= CFEXECUTE;
  533.             aflags &= ~CFEXECUTE;
  534.             break;
  535.         case 'E':
  536.             oflags &= ~CFEXECUTE;
  537.             aflags |= CFEXECUTE;
  538.             break;
  539.         case 'f':
  540.             oflags |= CFLIST;
  541.             break;
  542.         case 'k':
  543.             oflags |= CFKEEP;
  544.             aflags &= ~CFKEEP;
  545.             break;
  546.         case 'K':
  547.             oflags &= ~CFKEEP;
  548.             aflags |= CFKEEP;
  549.             break;
  550.         case 'l':
  551.             oflags |= CFLOCAL;
  552.             break;
  553.         case 'm':
  554.             oflags |= CFMAIL;
  555.             break;
  556.         case 'o':
  557.             oflags |= CFOLD;
  558.             aflags &= ~CFOLD;
  559.             break;
  560.         case 'O':
  561.             oflags &= ~CFOLD;
  562.             aflags |= CFOLD;
  563.             break;
  564.         case 'v':
  565.             oflags |= CFVERBOSE;
  566.             break;
  567.         case 'z':
  568.             oflags |= CFCOMPRESS;
  569.             break;
  570.         case 'Z':
  571.             oflags &= ~CFCOMPRESS;
  572.             break;
  573.         }
  574.         argp++;
  575.     }
  576. }
  577.  
  578. char *init (argc,argv)
  579. int argc;
  580. char **argv;
  581. {
  582.     char buf[STRINGLENGTH],*p;
  583.     char username[STRINGLENGTH];
  584.     register char *supfname,*q,*arg;
  585.     register COLLECTION *c,*lastC;
  586.     register FILE *f;
  587.     register int bogus;
  588.     register struct passwd *pw;
  589.     register TREE *t;
  590.     TREE *collT;            /* collections we are interested in */
  591.     long timenow;            /* startup time */
  592.     int checkcoll ();
  593.     int oflags,aflags;
  594.     int cwant;
  595. #ifdef    MACH
  596. #ifdef    __STDC__
  597.     void (*oldsigsys)();
  598. #else
  599.     int (*oldsigsys)();
  600. #endif
  601. #endif /* MACH */
  602.     char *fmttime();
  603.  
  604.     sysflag = FALSE;        /* not system upgrade */
  605.     timeflag = FALSE;        /* don't print times */
  606. #if    MACH
  607.     rpauseflag = FALSE;        /* don't disable resource pausing */
  608. #endif    /* MACH */
  609.     xpatchflag = FALSE;        /* not normally crosspatched */
  610.     scmdebug = 0;            /* level zero, no SCM debugging */
  611.     portdebug = FALSE;        /* no debugging ports */
  612.  
  613.     collT = NULL;
  614.     oflags = aflags = 0;
  615.     while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
  616.         doswitch (&argv[1][1],&collT,&oflags,&aflags);
  617.         --argc;
  618.         argv++;
  619.     }
  620.     if (argc == 1 && !sysflag)
  621.         logquit (1,"Need either -s or supfile");
  622. #if    MACH
  623.     oldsigsys = signal (SIGSYS,SIG_IGN);
  624.     if (rpauseflag != TRUE)
  625.         if (syscall (SYS_rpause,ENOSPC,RPAUSE_ALL,RPAUSE_DISABLE) < 0)
  626.         rpauseflag = TRUE;
  627.     (void) signal (SIGSYS,oldsigsys);
  628. #endif    /* MACH */
  629.     if (sysflag)
  630.         (void) sprintf (supfname = buf,
  631.                     timeflag?FILESUPTDEFAULT:FILESUPDEFAULT,
  632.                     DEFDIR);
  633.     else {
  634.         supfname = argv[1];
  635.         if (strcmp (supfname,"-") == 0)
  636.             supfname = "";
  637.         --argc;
  638.         argv++;
  639.     }
  640.     cwant = argc > 1;
  641.     while (argc > 1) {
  642.         t = Tinsert (&collT,argv[1],TRUE);
  643.         t->Twant = TRUE;
  644.         --argc;
  645.         argv++;
  646.     }
  647.     if ((p = (char *)getlogin()) ||
  648.         ((pw = getpwuid ((int)getuid())) && (p = pw->pw_name)))
  649.         (void) strcpy (username,p);
  650.     else
  651.         *username = '\0';
  652.     if (*supfname) {
  653.         f = fopen (supfname,"r");
  654.         if (f == NULL)
  655.             logquit (1,"Can't open supfile %s",supfname);
  656.     } else
  657.         f = stdin;
  658.     firstC = NULL;
  659.     lastC = NULL;
  660.     bogus = FALSE;
  661.     while (p = fgets (buf,STRINGLENGTH,f)) {
  662.         q = index (p,'\n');
  663.         if (q)  *q = '\0';
  664.         if (index ("#;:",*p))  continue;
  665.         arg = nxtarg (&p," \t");
  666.         if (*arg == '\0') {
  667.             logerr ("Missing collection name in supfile");
  668.             bogus = TRUE;
  669.             continue;
  670.         }
  671.         if (cwant) {
  672.             register TREE *t;
  673.             if ((t = Tsearch (collT,arg)) == NULL)
  674.                 continue;
  675.             t->Tcount++;
  676.         }
  677.         c = (COLLECTION *) malloc (sizeof(COLLECTION));
  678.         if (firstC == NULL)  firstC = c;
  679.         if (lastC != NULL) lastC->Cnext = c;
  680.         lastC = c;
  681.         if (parsecoll(c,arg,p) < 0) {
  682.             bogus = TRUE;
  683.             continue;
  684.         }
  685.         c->Cflags |= oflags;
  686.         c->Cflags &= ~aflags;
  687.         if (t = Tsearch (collT,c->Cname)) {
  688.             c->Cflags |= t->Toflags;
  689.             c->Cflags &= ~t->Taflags;
  690.         }
  691.         if ((c->Cflags&CFMAIL) && c->Cnotify == NULL) {
  692.             if (*username == '\0')
  693.                 logerr ("User unknown, notification disabled");
  694.             else
  695.                 c->Cnotify = salloc (username);
  696.         }
  697.         if (c->Cbase == NULL) {
  698.             (void) sprintf (buf,FILEBASEDEFAULT,c->Cname);
  699.             c->Cbase = salloc (buf);
  700.         }
  701.     }
  702.     if (bogus)  logquit (1,"Aborted due to supfile errors");
  703.     if (f != stdin)  (void) fclose (f);
  704.     if (cwant)  (void) Tprocess (collT,checkcoll);
  705.     Tfree (&collT);
  706.     if (firstC == NULL)  logquit (1,"No collections to upgrade");
  707.     timenow = time ((long *)NULL);
  708.     if (*supfname == '\0')
  709.         p = "standard input";
  710.     else if (sysflag)
  711.         p = "system software";
  712.     else
  713.         (void) sprintf (p = buf,"file %s",supfname);
  714.     loginfo ("SUP %d.%d (%s) for %s at %s",PROTOVERSION,PGMVERSION,
  715.         scmversion,p,fmttime (timenow));
  716.     return (salloc (supfname));
  717. }
  718.  
  719. checkcoll (t)
  720. register TREE *t;
  721. {
  722.     if (!t->Twant)  return (SCMOK);
  723.     if (t->Tcount == 0)
  724.         logerr ("Collection %s not found",t->Tname);
  725.     if (t->Tcount > 1)
  726.         logerr ("Collection %s found more than once",t->Tname);
  727.     return (SCMOK);
  728. }
  729.